package com.lap.framework.dto.page;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.lap.framework.exception.PageSizeException;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.ToString;

/**
 * <strong> 使用方式 </strong>
 *
 * <pre>
 * <ol>
 *  <li>继承方式：</li>
 *   {@code
 *   public class TestQuery extends PageRequest {
 *       private String name;
 *   }
 *   }
 *  <li>接口多参数模式：</li>
 *  {@code
 *   @RestController
 *   @RequestMapping("api/tests")
 *   public class TestController {
 *
 *     @GetMapping
 *     public Test getTest(TestQuery query, PageRequest page) {
 *         return "";
 *     }
 *
 *   }
 *   }
 *  <li>组合方式：</li>
 *  {@code
 *  public class TestQuery {
 *     private PageRequest page;
 *  }
 *  }
 *
 * </ol>
 * </pre>
 *
 * @author Shuisheng Lao(劳水生)
 * @version 0.0.1
 */
@Getter
@ToString
@Schema(description = "分页请求信息")
public class PageRequest {
  private static final int CUR_PAGE = 1;
  private static final int PAGE_SIZE = 10;
  private static final int MAX_PAGE_SIZE = 20000;

  @Schema(description = "当前页")
  private Integer curPage = CUR_PAGE;

  @Schema(description = "每页数量")
  private Integer pageSize = PAGE_SIZE;

  @Schema(description = "排序字段")
  private String sortField;

  @Schema(description = "排序值:desc|asc")
  private String sortValues;

  public PageRequest() {
    this(CUR_PAGE);
  }

  public PageRequest(Integer curPage) {
    this(curPage, PAGE_SIZE);
  }

  public PageRequest(Integer curPage, Integer pageSize) {
    this.curPage = getDefault(curPage, CUR_PAGE);
    this.pageSize = getDefaultPageSize(pageSize);
  }

  private Integer getDefaultPageSize(Integer pageSize) {
    Integer value = getDefault(pageSize, PAGE_SIZE);
    if (value > MAX_PAGE_SIZE)
      throw new PageSizeException("The page value exceeds the maximum value: " + MAX_PAGE_SIZE);

    return value;
  }

  private Integer getDefault(Integer value, Integer defaultValue) {
    return (value == null || value <= 0) ? defaultValue : value;
  }

  public PageRequest setCurPage(Integer curPage) {
    this.curPage = getDefault(curPage, CUR_PAGE);
    return this;
  }

  public PageRequest setPageSize(Integer pageSize) {
    this.pageSize = getDefault(pageSize, PAGE_SIZE);
    return this;
  }

  public PageRequest setSortField(String sortField) {
    this.sortField = sortField;
    return this;
  }

  public PageRequest setSortValues(String sortValues) {
    this.sortValues = sortValues;
    return this;
  }

  @JsonIgnore
  public int getStartRow() {
    return (this.curPage - 1) * this.pageSize;
  }
}
